#ifndef _WIN_IMPL_EXPECTION_
#define _WIN_IMPL_EXPECTION_


#include <exception>
#include <sstream>
#include <string>
#include <algorithm>


namespace sd
{
namespace tools
{


typedef int ErrroCode;

std::string  unicodeToAnsi(const std::wstring&);
std::wstring ansiToUnicode(const std::string&);
std::wstring getWinErrorAsString( ErrroCode );


class wexception: public std::exception
{
public:
	wexception(){}
	virtual ~wexception(){}
	virtual std::wstring wwhat()const=0;
	virtual const char * __CLR_OR_THIS_CALL what() const{ buffer_=unicodeToAnsi( wwhat() ); return buffer_.c_str(); }
private:
	mutable std::string buffer_;
};


namespace win
{




class WinImplException: public wexception
{
public:
	virtual ~WinImplException()throw(){}
	WinImplException( const WinImplException& ref )throw(): text_( ref.text_ ), code_( ref.code_ ){}
	
	template< class T >
	void build( const T& str )
	{
		std::wstringstream st;
		st << str << L"( " << code_ << " : \"" << getWinErrorAsString( code_ ) << L"\" )";
		wtext_ = st.str();
	}


	
	
	WinImplException( const std::wstring& text ) throw(): code_( getLastError() )
	{
		build( text );
	}
	
	WinImplException( const std::string& text ) throw(): code_( getLastError() )
	{
		build(ansiToUnicode(text) );
	}
	

	virtual std::wstring wwhat()const throw()
	{
		return wtext_;
	}
private:
	ErrroCode getLastError();
	WinImplException()throw(){}
	std::string text_;
	std::wstring wtext_;
	int code_;
};


}//sd
}//tools
}//win


#endif//_WIN_IMPL_EXPECTION_